/**
 * 与SatelliteScan.js一样
 * 为避免多个viewer竞争条件，单独控制
 * window.miniToEnemyViewer
 */
import * as Cesium from "cesium";

function transform(satelliteScane, angle, axis) {
    if (!Cesium.defined(satelliteScane)) {
        return;
    }
    angle = Cesium.Math.toRadians(angle);
    const rotation = new Cesium.Matrix3();
    const quaternion = new Cesium.Quaternion();
    Cesium.Quaternion.fromAxisAngle(axis, angle, quaternion);
    Cesium.Matrix3.fromQuaternion(quaternion, rotation);
    // 旋转锥体
    const rotationMatrix = new Cesium.Matrix4();
    Cesium.Matrix4.fromRotationTranslation(rotation, new Cesium.Cartesian3(0, 0, 0), rotationMatrix);
    Cesium.Matrix4.multiplyByMatrix3(satelliteScane._matrix, rotation, satelliteScane._matrix);

    //调整顶点位置
    const coordinate = LonLat.fromCartesian(satelliteScane._surface, window.miniToEnemyViewer);
    const inverseMatrix = new Cesium.Matrix4();
    Cesium.Matrix4.inverseTransformation(satelliteScane._matrix, inverseMatrix);
    //变换前锥体的顶点坐标
    const topPosition = Cesium.Cartesian3.fromDegrees(coordinate.lon, coordinate.lat, satelliteScane._height);
    const localtop = new Cesium.Cartesian3();
    Cesium.Matrix4.multiplyByPoint(inverseMatrix, topPosition, localtop);
    //变换后顶点的坐标
    const newtop = new Cesium.Cartesian3();
    Cesium.Matrix4.multiplyByPoint(rotationMatrix, localtop, newtop);
    const diff = new Cesium.Cartesian3();
    Cesium.Cartesian3.subtract(localtop, newtop, diff);

    Cesium.Matrix4.multiplyByTranslation(satelliteScane._matrix, diff, satelliteScane._matrix);
    satelliteScane.updateMatrix(satelliteScane._matrix);
}
function update(scatelliteScan) {
    const material = scatelliteScan.scanPrimitive.appearance.material;
    const viewer = window.miniToEnemyViewer;
    if (scatelliteScan.path) {
        const center = scatelliteScan.path.position.getValue(viewer.clock.currentTime);
        scatelliteScan._position = center;
        const carto = LonLat.fromCartesian(center, viewer);
        const surface = Cesium.Cartesian3.fromDegrees(carto.lon, carto.lat);
        scatelliteScan._surface = surface;
        scatelliteScan._height = carto.height;
        const offset = new Cesium.Cartesian3(0, 0, carto.height / 2);

        const baseMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(surface);
        const matrix = Cesium.Matrix4.multiplyByTranslation(
            baseMatrix,
            offset,
            new Cesium.Matrix4
        );
        scatelliteScan._matrix = matrix; // 直接替换而不是累积


        scatelliteScan.updateMatrix(matrix);
        scatelliteScan.imagePrimitive.position = center;
        scatelliteScan.transform(scatelliteScan.rotation);
        if (scatelliteScan.tracked) {
            scatelliteScan.trackSatellite();
        }
    }
    let offset = material.uniforms.offset;
    offset -= 0.005 * scatelliteScan.speed;
    if (offset > 1.0) {
        offset = 0.0;
    }
    scatelliteScan.scanPrimitive.appearance.material.uniforms.offset = offset;
}
function createGuid() {
    return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
        const r = (Math.random() * 16) | 0;
        const v = c === "x" ? r : (r & 0x3) | 0x8;
        return v.toString(16);
    });
}
class Graphic {
    /**
     * 所有CesiumPro自定义图形基类
    */
    constructor(options) {
        this._options = Cesium.defaultValue(options, {});
        this._id = Cesium.defaultValue(options.id, createGuid());
        this._primitive = null;
        this._oldPrimitive = null;
        this._definedChanged = new SatelliteScan_Event();
        this._loadEvent = new SatelliteScan_Event();
        this._clampToGround = Cesium.defaultValue(!!options.clampToGround, false);
        this._show = Cesium.defaultValue(options.show, true);
        this._removed = false;
        this._allowPicking = Cesium.defaultValue(options.allowPicking, true);
        this._property = options.property;
    }
    get id() {
        return this._id;
    }
    /**
     * 图形的属性信息，当元素被拾取的时候该属性会通过id字段返回
     * @type {any}
     */
    get property() {
        return this._property;
    }
    /**
     * 获得或设置图形是否允许被拾取
     * @type {Boolean}
     */
    get allowPicking() {
        return this._allowPicking;
    }
    set allowPicking(v) {
        if ((!!v) !== this._allowPicking) {
            this.definedChanged.raise('allowPicking', v, this._allowPicking);
            this._allowPicking = v;
            this.updatePrimitive && this.updatePrimitive();
        }
    }
    /**
     * 获取或设置图形是否贴地
     * @type {Boolean}
     */
    get clampToGround() {
        return this._clampToGround;
    }
    set clampToGround(val) {
        if (val === this._clampToGround) {
            return

        }
        this.definedChanged.raise('clampToGround', val, this._clampToGround);
        this._clampToGround = val;
        this.updatePrimitive();
    }
    /**
     * 显示或隐藏图形
     * @type {Boolean}
     */
    get show() {
        return this._show;
    }
    set show(val) {
        if (val === this._show) {
            return
        }
        this.definedChanged.raise('show', val, this._show);
        this._show = val;
        this.primitive && (this.primitive.show = val);
    }
    /**
     * 图形对象，包含了渲染图形所老百姓的几何信息和材质
     * @readonly
     */
    get primitive() {
        return this._primitive;
    }
    /**
     * 要素的属性发生变化时触发的事件。
     * 事件订阅者接收3个参数，第一个是发生变化的属性，第二是个变化后的属性，
     * 第三个是变化前的属性
     */
    get definedChanged() {
        return this._definedChanged;
    }
    /**
     * 得到一个promise对象，指示图形是否创建完成
     * @type {Promise}
     */
    get readyPromise() {
        if (!this.primitive) {
            return new Primise();
        }
        return this.primitive.readyPromise;
    }
    /**
     * @private
     */
    get material() {
        if (this.primitive) {
            return this.primitive.appearance.material;
        }
    }
    toJson() {
        if (!Cesium.defined(this.primitive)) {
            return;
        }
        return JSON.parse(JSON.stringify(this._options))
    }
    /**
     * @private
     */
    update() { }
    /**
     * 更新要素外观材质相关的属性
     * @private
     * @param {*} k
     * @param {*} v
     */
    updateAttribute(k, v) {
        if (this.isDestroyed()) {
            return;
        }
        if (!this.primitive) {
            return;
        }
        const appearance = this.primitive.appearance;
        const material = appearance.material;
        if (!material) {
            return;
        }
        const uniforms = material.uniforms;
        if (!uniforms) {
            return;
        }
        uniforms[k] = v;
    }
    /**
     * 将图形要素直接添加到指定viewer
     * @param {Viewer} viewer viewer对象
     */
    addTo(viewer) {
        if (!Cesium.defined(this.primitive)) {
            return;
        }
        viewer.scene.primitives.add(this.primitive)
    }
    zoomTo(viewer) {
        if (!Cesium.defined(this.primitive)) {
            return;
        }
        console.log(this.primitive);
        viewer.flyTo(this.primitive)
    }
    /**
     * 将当前要素从场景中移除
     * @returns 被移除的要素
     */
    remove() {
        if (!Cesium.defined(this.primitive)) {
            return;
        }
        viewer.scene.primitives.remove(this.primitive)
    }
    isDestroyed() {
        return false;
    }
    destroy() {
        this.remove();
        if (this.primitive && !this.primitive.isDestroyed()) {
            this.primitive.destroy();
            this.primitive = undefined;
        }
        Cesium.destroyObject(this);
    }
}
class LonLat {
    /**
     * 用经纬度（度）和海拔（米）描述一个地理位置。
     * @param {Number} lon 经度，单位：度
     * @param {Number} lat 经度，单位：度
     * @param {Number} alt 海拔，单位：米
     */
    constructor(lon, lat, alt) {
        if (!Cesium.defined(lon)) {
            throw new Error('longitude is required.')
        }
        if (!Cesium.defined(lat)) {
            throw new Error('latitude is required.')
        }
        this.lon = lon;
        this.lat = lat;
        this.alt = Cesium.defaultValue(alt, 0);
    }
    get height() {
        return this.alt;
    }
    /**
     * 转为屏幕坐标
     * @param {Cesium.Scene} scene
     * @returns {Cesium.Cartesian2} 屏幕坐标
     */
    toPixel(scene) {
        return LonLat.toPixel(this, scene);
    }
    /**
     * 转为笛卡尔坐标
     * @returns {Cesium.Cartesian3} 笛卡尔坐标
     */
    toCartesian() {
        return LonLat.toCartesian(this);
    }
    /**
     * 转为地理坐标
     * @returns {Cesium.Cartographic} 地理坐标
     */
    toCartographic() {
        return LonLat.toCartographic(this)
    }
    /**
     * 获得该点的弧度形式
     * @returns 弧度表示的点
     */
    getRadias() {
        return {
            lon: Cesium.Math.toRadians(this.lon),
            lat: Cesium.Math.toRadians(this.lat),
            alt
        }
    }
    /**
     * 判断该点是否在场景内，且在球的正面
     * @returns {Boolean} 可见性
     */
    isVisible(viewer) {
        return LonLat.isVisible(this, viewer)
    }
    /**
     * 转为字符串
     * @returns 表示该点位置的字符串
     */
    toString() {
        return `{lon: ${this.lon}, lat: ${this.lat}, alt: ${this.alt}}`
    }
    /**
     * 转为JSON对象
     * @returns 表示该点位置的对象
     */
    toJson() {
        return {
            lon: this.lon,
            lat: this.lat,
            alt: this.alt
        }
    }
    /**
     * 从地理点坐标转换成数组
     * @returns 表示该点位置的数组
     */
    toArray() {
        return [this.lon, this.lat, this.alt];
    }
    /**
     * 判断一个点在当前场景是否可见。这里的可见指的是是否在屏幕范围内且在球的正面。
     * @param {LonLat} point 点
     * @param {Cesium.Viewer} viewer Viewer对象
     * @returns {Boolean} 可见性
     */
    static isVisible(point, viewer) {
        if (viewer instanceof Cesium.Viewer === false) {
            throw new Error('viewer不是一个有效的Cesium.Viewer对象')
        }
        if (!Cesium.defined(point)) {
            return false;
        }
        const position = LonLat.toCartesian(point);
        if (!position) {
            return false;
        }
        if (viewer.scene.mode === Cesium.SceneMode.SCENE3D) {
            const visibility = new Cesium.EllipsoidalOccluder(Cesium.Ellipsoid.WGS84, viewer.camera.position)
                .isPointVisible(position);
            if (!visibility) {
                return false;
            }
            const windowPosition = LonLat.toPixel(point, viewer.scene);
            if (!Cesium.defined(windowPosition)) {
                return false;
            }
            const width = viewer.canvas.width || viewer.canvas.clientWidth;
            const height = viewer.canvas.height || viewer.canvas.clientHeight;
            return (windowPosition.x > 0 && windowPosition.x < width) && (windowPosition.y > 0 && windowPosition.y < height);
        } else if (viewer.scene.mode === Cesium.SceneMode.SCENE2D) {
            const frustum = viewer.scene.camera.frustum;
            const {
                positionWC,
                directionWC,
                upWC
            } = viewer.scene.camera;
            const cullingVolume = frustum.computeCullingVolume(positionWC, directionWC, upWC);
            const bounding = Cesium.BoundingSphere.projectTo2D(new BoundingSphere(position, 1));
            const visibility = cullingVolume.computeVisibility(bounding);
            return visibility === Cesium.Intersect.INSIDE || visibility === Cesium.Intersect.INERSECTING
        }
    }
    /**
     * 转屏幕坐标
     * @param {LonLat|Cesium.Cartesian3|Cesium.Cartographic} point
     * @param {Cesium.Scene} scene
     * @returns 对应的屏幕坐标
     */
    static toPixel(point, scene) {
        if (!Cesium.defined(scene)) {
            throw new Error('scene未定义。')
        }
        if (!Cesium.defined(point)) {
            return undefined
        }
        const cartesian = LonLat.toCartesian(point);
        if (!Cesium.defined(cartesian)) {
            return undefined;
        }
        return Cesium.SceneTransforms.wgs84ToWindowCoordinates(
            scene,
            cartesian,
        );
    }
    /**
     * 转弧度坐标
     * @param {LonLat} point
     * @returns 用弧度表示的坐标点
     */
    static toCartographic(point, viewer) {
        if (!Cesium.defined(point)) {
            throw new Error('point is not defined.')
        }
        if (point instanceof LonLat) {
            return Cesium.Cartographic.fromDegrees(point.lon, point.lat, point.alt);
        } else if (point instanceof Cesium.Cartesian3) {
            return Cesium.Cartographic.fromCartesian(point);
        } else if (point instanceof Cesium.Cartographic) {
            return point;
        } else if (point instanceof Cesium.Cartesian2) {
            const cartesian = LonLat.toCartesian(point, viewer);
            return LonLat.toCartographic(cartesian)
        }
    }
    /**
     * 转笛卡尔坐标
     * @param {LonLat|Cesium.Cartesian3|Cesium.Cartographic|Cesium.Cartesian2} point
     * @param {Viewer} [viewer] viewer对象， 如果point是Cesium.Cartesian2类型，该参数需要被提供
     * @returns 用笛卡尔坐标表示的点
     */
    static toCartesian(point, viewer) {
        if (!Cesium.defined(point)) {
            return undefined;
        }
        if (point instanceof Cesium.Cartesian3) {
            return point;
        }
        if (point instanceof Cesium.Cartographic) {
            return Cesium.Cartographic.toCartesian(point)
        }
        if (point instanceof LonLat) {
            return Cesium.Cartesian3.fromDegrees(point.lon, point.lat, point.alt)
        }
        if (point instanceof Cesium.Cartesian2) {
            if (!viewer) {
                return;
            }
            const ray = viewer.scene.camera.getPickRay(point);
            return viewer.scene.globe.pick(ray, viewer.scene);
        }

    }
    /**
     * 从一个笛卡尔坐标创建点
     * @param {Cesium.Cartesian3} cartesian 笛卡尔坐标点
     * @returns GeoPoint点
     */
    static fromCartesian(cartesian) {
        if (!Cesium.defined(cartesian)) {
            return undefined
        }
        const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
        if (!Cesium.defined(cartographic)) {
            return undefined;
        }
        return LonLat.fromCartographic(cartographic)
    }
    /**
     * 从一个地理坐标点创建点
     * @param {Cesium.Cartographic} cartographic 地理坐标点
     * @returns GeoPoint点
     */
    static fromCartographic(cartographic) {
        if (!Cesium.defined(cartographic)) {
            throw new Error('cartographic is not defined.')
        }
        return new LonLat(
            Cesium.Math.toDegrees(cartographic.longitude),
            Cesium.Math.toDegrees(cartographic.latitude),
            cartographic.height
        )
    }
    /**
     * 从一个窗口坐标创建点
     * @param {Cesium.Cartesian2} pixel 窗口坐标
     * @param {Cesium.Viewer} viewer Viewer对象
     * @returns {LonLat} GeoPoint点
     */
    static fromPixel(pixel, viewer) {
        if (!viewer.scene.globe) {
            return undefined;
        }
        if (!Cesium.defined(pixel)) {
            throw new Error('pixel is not defined.')
        }
        if (viewer instanceof Cesium.Viewer === false) {
            throw new Error('viewer不是一个有效的Cesium.Viewer对象')
        }
        const ray = viewer.scene.camera.getPickRay(pixel);
        const cartesian = viewer.scene.globe.pick(ray, viewer.scene);
        if (!Cesium.defined(cartesian)) {
            return undefined;
        }
        return LonLat.fromCartesian(cartesian);
    }
    /**
     * 从经纬度创建点
     * @param {Number} lon 经度(度)
     * @param {Number} lat 纬度(度)
     * @param {Number} height 海拔(米)
     * @returns {LonLat}
     */
    static fromDegrees(lon, lat, height) {
        return new LonLat(lon, lat, height);
    }
    /**
     * 获得一个经纬度数组
     * @param {*} positions
     * @returns {LonLat[]} 经纬度数组
     * @example
     * LonLat.fromDegreesArray([110, 30, 111, 31])
     */
    static fromDegreesArray(positions) {
        const ps = [];
        for (let i = 0, n = positions.length; i < n; i += 2) {
            ps.push(new LonLat(positions[i], positions[i + 1]));
        }
        return ps;
    }
    /**
     * 获得一个经纬度数组
     * @param {*} positions
     * @returns {LonLat[]} 经纬度数组
     * @example
     */
    static fromDegreesArrayHeights(positions) {
        const ps = [];
        for (let i = 0, n = positions.length; i < n; i += 3) {
            ps.push(new LonLat(positions[i], positions[i + 1], positions[i + 2]));
        }
        return ps;
    }
    /**
     * 从经纬度创建点
     * @param {Number} lon 经度(弧度)
     * @param {Number} lat 纬度(弧度)
     * @param {Number} height 海拔(米)
     * @returns {LonLat}
     */
    static fromRadians(lon, lat, height) {
        return new LonLat(Cesium.Math.toDegrees(lon), Cesium.Math.toDegrees(lat), height);
    }
    /**
     * 判断一个点或经纬度是否在中国范围内（粗略）
     * @param  {LonLat|Number[]} args
     * @returns 如果在中国范围内，返回true
     */
    static inChina(...args) {
        if (args.length === 1) {
            const p = args[0];
            if (args[0] instanceof LonLat) {
                return LonLat.inChina(p.lon, p.lat)
            }
        } else {
            const lon = +args[0];
            const lat = +args[1];
            return lon > 73.66 && lon < 135.05 && lat > 3.86 && lat < 53.55
        }
    }
    /**
     * 从经纬度数组创建点, 经纬度数组，经度在前，纬度在后
     * @param {Array} lonlat
     * @returns {LonLat}
     */
    static fromArray(lonlat) {
        return new LonLat(...lonlat)
    }
    /**
     * 从经纬度数组创建点, 经纬度数组，经度在前，纬度在后
     * @param {Object} lonlat
     * @returns {LonLat}
     */
    static fromJson(lonlat) {
        return new LonLat(lonlat.lon, lonlat.lat, lonlat.alt)
    }
    /**
     * 判断对象是不是一个有效的点
     * @param {any} v
     */
    static isValid(v) {
        if (v instanceof LonLat) {
            if (!Cesium.defined(v.lon)) {
                return false;
            }
            if (!Cesium.defined(v.lat)) {
                return false;
            }
            if (!Cesium.defined(v.alt)) {
                return false;
            }
            return true
        }
        if (v instanceof Cesium.Cartesian3) {
            if (!Cesium.defined(v.x)) {
                return false;
            }
            if (!Cesium.defined(v.y)) {
                return false;
            }
            if (!Cesium.defined(v.z)) {
                return false;
            }
            return true;
        }
        return false;
    }
}
class SatelliteScan extends Graphic {
    /**
     * 卫星扫描
     * @param {*} options 具有以下属性
     * @param {Bool} [options.show=true] 是否可见
     * @param {Cartesian3} [options.position] 卫星的位置
     * @param {Entity} [options.path] 卫星运动轨道,该属性将覆盖position
     * @param {Number} [options.radius] 卫星在地面的扫描半径
     * @param {Bool} [options.inverse=false] 扫描方向，该值为true卫星将从下向上扫描
     * @param {Bool} [options.tracked=false] 是否跟踪卫星
     * @param {Color} [options.color] 扫描波颜色
     * @param {Bool} [option.image] 卫星图标，如果定义了model该属性将不生效
     * @param {Bool} [options.model=false] 卫星模型
     * @param {Cartesian3} [option.axis=Cartesian3(1,0,0)] 卫星扫描方向偏转的坐标轴
     * @param {Number} [options.rotation] 扫描波在方向偏转角度
     * @param {Bool} [option.animate=true] 是否动态扫描
     * @param {number} [options.thickness=0.3] 扫描波每一片的厚度(宽度)
     * @param {number} [options.slices=20] 扫描波的分片数量
     * @param {number} [options.lenght=1] 椎体长度
     */
    constructor(options) {
        let viewer = window.miniToEnemyViewer;
        console.log('viewer:' +  viewer)
        options.path && (options.position = options.path.position.getValue(viewer.clock.currentTime));
        super(options);

        this._clampToGround = false;
        if (!Cesium.defined(options.position)) {
            throw new Error('参数options必须定义position或path属性。')
        }
        const cartographic = LonLat.toCartographic(options.position, viewer);
        this._position = LonLat.toCartesian(options.position);
        this._thickness = Cesium.defaultValue(options.thickness, 0.3);
        this._slices = Cesium.defaultValue(options.slices, 30);
        this.speed = Cesium.defaultValue(options.speed, 0.5);
        this._lenght = Cesium.defaultValue(options.lenght, 1);

        /**
         * 卫星所在的高度
         */
        this._height = cartographic.height;
        /**
         * 卫星在地面的投影位置
         */
        this._surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude);
        /**
         * 卫星在地面的扫描半径
         * @type {Number}
         * @readonly
         */
        this.radius = options.radius || this._height * 0.5;

        this._inverse = options.inverse || false;
        this._animation = Cesium.defined(options.animation) ? options.animation : true;
        this._show = Cesium.defined(options.show) ? options.show : true;

        this._color = options.color;
        /**
         * 卫星运动轨迹
         * @type {Entity}
         * @readonly
         */
        this.path = options.path;

        this._tracked = options.tracked || false;

        this._rotation = options.rotation;

        this._axis = options.axis;

        // this._matrix = Cesium.Matrix4.multiplyByTranslation(
        //     Cesium.Transforms.eastNorthUpToFixedFrame(this._surface),
        //     new Cesium.Cartesian3(0, 0, 0.5 * this._height),
        //     new Cesium.Matrix4()
        // );



        // 计算旋转角(弧度)
        let hpr = Cesium.HeadingPitchRoll.fromQuaternion(options.path.orientation.getValue(viewer.clock.currentTime));
        //移动位置
        let origin = options.position;
        //旋转角度Quaternion
        // let hpr = options.path.orientation;

        this._matrix =  Cesium.Transforms.headingPitchRollToFixedFrame(origin,hpr);
        const offset = new Cesium.Cartesian3(0, 0, 0.5 * this._lenght);
        Cesium.Matrix4.multiplyByTranslation(this._matrix, offset, this._matrix);

        this.transform(this._rotation);
        /**
         * 表示卫星的图标,false表示不显示图标
         * @type {String|Boolean}
         */
        this.image = options.image;
        /**
         * 表示卫星的模型,false表示不显示模型
         * @type {String|Boolean}
         */
        this.model = options.model;
        this._primitive = new Cesium.PrimitiveCollection();
        this._primitive.name = 'SatelliteScan';
        this._loadEvent.addEventListener(() => {
            if (!window.miniToEnemyViewer) {
                return;
            }
            this.stopAnimate = window.miniToEnemyViewer.scene.preUpdate.addEventListener(() => {
                update(this);
            });
        });
        this.createGraphic();
    }
    updateMatrix(matrix) {
        if (!matrix) {
            return;
        }
        this._matrix = matrix;
        this.scanPrimitive.modelMatrix = matrix;
        var offset = this.scanPrimitive.appearance.material.uniforms.offset
        offset += 0.07
        // if (offset > 1.0) {
        //     offset = 0.0
        // }
        this.scanPrimitive.appearance.material.uniforms.offset = offset;
        // if (this.imagePrimitive) {
        //   this.imagePrimitive.position = Cesium.Matrix4.getTranslation(matrix, {});
        // }
        if (this.modelPrimitive) {
            this.modelPrimitive.modelMatrix = matrix;
        }
    }
    updatePrimitive() {
        this.createGraphic();
    }
    createGraphic() {
        if (this.model) {
            const model = Cesium.Model.fromGltf({
                url: this.model,
                // pixelOffset: new Cesium.Cartesian2(-10, 10)
            });
            this.modelPrimitive = this.primitive.add(model);
        }
        if (this.image) {
            const billboardCollection = new Cesium.BillboardCollection();
            this.primitive.add(billboardCollection);
            this.imagePrimitive = billboardCollection.add({
                image: this.image,
                position: this._position,
            });
        }
        /**
         * 卫星放射波锥体
         */
        const geometry = new Cesium.CylinderGeometry({
            length: this._lenght,
            topRadius: this.radius,
            bottomRadius: 0,
            vertextFormat: Cesium.MaterialAppearance.MaterialSupport.TEXTURED.vertextFormat
        });
        const instance = new Cesium.GeometryInstance({
            geometry,
        });
        const source = this.getShaderSorce();
        const material = new Cesium.Material({
            fabric: {
                type: 'satelliteMaterial',
                uniforms: {
                    color: this._color || Cesium.Color.WHITE,
                    repeat: this.slices, //锥体被分成30份
                    offset: 0.0,
                    thickness: this.thickness,
                    sign: this.inverse ? 1 : -1
                },
                source: source
            }
        });
        const primitive = new Cesium.Primitive({
            modelMatrix: this._matrix,
            show: this.show,
            geometryInstances: instance,
            appearance: new Cesium.MaterialAppearance({
                material: material
            }),
            asynchronous: false
        });
        this.scanPrimitive = this.primitive.add(primitive);
        if (this.stopAnimate) {
            this.stopAnimate();
        }
    }
    /**
     * 使相视视角一直跟要卫星
     */
    trackSatellite() {
        if (!window.miniToEnemyViewer) {
            return;
        }
        if (this._tracked) {
            const boundingSphere = new Cesium.BoundingSphere(this._position, this._height);
            window.miniToEnemyViewer.camera.viewBoundingSphere(boundingSphere);
            window.miniToEnemyViewer.camera.lookAtTransform(this._matrix);
        } else {
            window.miniToEnemyViewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
        }
    }
    /**
     * 是否反方向扫描，true表示从下向上扫描
     * @type {Boolean}
     * @readonly
     */
    get inverse() {
        return this._inverse;
    }
    set inverse(val) {
        this._inverse = val;
        if (this.scanPrimitive) {
            this.scanPrimitive.appearance.material.uniforms.sign = val ? 1 : -1;
        }
    }
    get slices() {
        return this._slices;
    }
    set slices(val) {
        this._slices = val;
        if (this.scanPrimitive) {
            this.scanPrimitive.appearance.material.uniforms.repeat = val;
        }
    }
    /**
     * 厚度,有效值0~1
     * @type {number}
     */
    get thickness() {
        return this._thickness;
    }
    set thickness(val) {
        if (val < 0) {
            val = 0;
        }
        if (val > 1) {
            val = 1;
        }
        if (this.scanPrimitive) {
            this.scanPrimitive.appearance.material.uniforms.thickness = val;
        }
    }
    /**
     * 卫星扫描波在各方向的偏转角度
     * @type {Cesium.Cartesian3}
     * @readonly
     */
    get rotation() {
        return this._rotation;
    }
    set rotation(val) {
        this._rotation = val;
        this.transform(val);
    }
    /**
     * 卫星扫描该向偏转轴
     * @type {Cartesian3}
     * @readonly
     */
    get axis() {
        return this._axis;
    }
    /**
     * 是否追踪卫星
     * @type {Bool}
     */
    get tracked() {
        return this._tracked;
    }
    set tracked(val) {
        if (val === this._tracked) return;
        this._tracked = val;
        this.trackSatellite();
    }
    /**
     * 扫描波颜色
     * @type {Cesium.Color}
     */
    get color() {
        return this._color;
    }
    set color(val) {
        this._color = val;
        this.scanPrimitive && (this.scanPrimitive.appearance.material.uniforms.color = val);
    }
    /**
     * 是否动态扫描
     * @type {Boolean}
     */
    get animation() {
        return this._animation;
    }
    set animation(val) {
        if (val === this._animation) {
            return;
        }
        if (val) {
            this.stopAnimate = window.miniToEnemyViewer.scene.preUpdate.addEventListener(() => {
                update(this);
            });
        } else {
            this.stopAnimate && this.stopAnimate();
            this.stopAnimate = undefined;
        }
        this._animation = val;
    }
    getShaderSorce() {
        return `
                uniform vec4 color;
                uniform float repeat;
                uniform float offset;
                uniform float thickness;
                uniform float sign;
                czm_material czm_getMaterial(czm_materialInput inputM){
                    czm_material material=czm_getDefaultMaterial(inputM);
                    float sp=1.0/repeat;
                    vec2 st=inputM.st;
                    float dis=distance(st,vec2(0.5));
                    float m=mod(dis + sign * offset,sp);
                    float a=step(sp*(1.0-thickness),m);
                    material.diffuse=color.rgb;
                    material.alpha=a*color.a;
                    return material;
                }`
    }
    /**
     * 定位到扫描波所在的位置
     */
    zoomTo(duration) {
        if (!this.show || !window.miniToEnemyViewer) {
            return;
        }
        const boundingSphere = new Cesium.BoundingSphere(this._position, this._height);
        window.miniToEnemyViewer.camera.flyToBoundingSphere(boundingSphere, {
            duration
        });
    }
    transform(angle) {
        if (!angle) {
            return;
        }
        if (angle.x) {
            transform(this, angle.x, new Cesium.Cartesian3(1, 0, 0));
        }
        if (angle.y) {
            transform(this, angle.y, new Cesium.Cartesian3(0, 1, 0));
        }
        if (angle.z) {
            transform(this, angle.z, new Cesium.Cartesian3(0, 0, 1));
        }
    }
    getLenght() {
        return this._lenght;
    }
    setLength(lenght) {
        this._lenght = lenght;
    }
}
class SatelliteScan_Event {
    /**
     * 事件管理器
     * @example
     * const addMarkerEvent=new Event();
     * function saveMark(marker){
     *  console.log("添加了一个marker",marker.id)
     * }
     * addMarkerEvent.on(saveMark)
     * const mark=viewer.entities.add({
     *  id:"mark1",
     *  billboard:{
     *    image:"./icon/pin.png"
     *  }
     * })
     * addMarkerEvent.emit(mark)
     */
    constructor() {
        this._listeners = [];
        this._scopes = [];
        this._toRemove = [];
        this._insideRaiseEvent = false;
    }

    /**
     * 当前订阅事件的侦听器个数
     * @type {Number}
     */
    get numberOfListeners() {
        return this._listeners.length - this._toRemove.length;
    }

    /**
     * 注册事件触发时执行的回调函数
     * @param {Function} listener 事件触发时执行的回调函数
     * @param {Object} [scope] 侦听器函数中this的指针
     * @return {Function} 用于取消侦听器监测的函数
     *
     * @see Event#removeEventListener
     * @see Event#raise
     */

    addEventListener(listener, scope) {
        if (typeof listener !== 'function') {
            throw new Error('侦听器应该是一个函数');
        }

        this._listeners.push(listener);
        this._scopes.push(scope);

        const event = this;
        return function () {
            event.removeEventListener(listener, scope);
        };
    }

    /**
     * 注销事件触发时的回调函数
     * @param {Function} listener 将要被注销的函数
     * @param {Object} [scope] 侦听器函数中this的指针
     * @return {Boolean} 如果为真，事件被成功注销，否则，事件注销失败
     *
     * @see Event#addEventListener
     * @see Event#raise
     */
    removeEventListener(listener, scope) {
        if (typeof listener !== 'function') {
            throw new Error('侦听器应该是一个函数');
        }
        const listeners = this._listeners;
        const scopes = this._scopes;

        let index = -1;
        for (let i = 0; i < listeners.length; i++) {
            if (listeners[i] === listener && scopes[i] === scope) {
                index = i;
                break;
            }
        }

        if (index !== -1) {
            if (this._insideRaiseEvent) {
                this._toRemove.push(index);
                listeners[index] = undefined;
                scopes[index] = undefined;
            } else {
                listeners.splice(index, 1);
                scopes.splice(index, 1);
            }
            return true;
        }

        return false;
    }

    /**
     * 触发事件
     * @param {*} arguments 此方法接受任意数据的参数并传递给侦听器函数
     *
     * @see Event#addEventListener
     * @see Event#removeEventListener
     */
    raise() {
        this._insideRaiseEvent = true;

        let i;
        const listeners = this._listeners;
        const scopes = this._scopes;
        let {
            length,
        } = listeners;

        for (i = 0; i < length; i++) {
            const listener = listeners[i];
            if (Cesium.defined(listener)) {
                listeners[i].apply(scopes[i], arguments);
            }
        }

        // Actually remove items removed in removeEventListener.
        const toRemove = this._toRemove;
        length = toRemove.length;
        // 降序排列，从后往前删
        if (length > 0) {
            toRemove.sort(compareNumber);
            for (i = 0; i < length; i++) {
                const index = toRemove[i];
                listeners.splice(index, 1);
                scopes.splice(index, 1);
            }
            toRemove.length = 0;
        }

        this._insideRaiseEvent = false;
    }
    raiseEvent() {
        this.raise(...arguments);
    }
};
export { SatelliteScan, LonLat };
